今天來探索一下有關CSS的SASS/SCSS控制
首先看一下MDN的說明
https://developer.mozilla.org/en-US/docs/Glossary/CSS_preprocessor
CSS preprocessor:A CSS preprocessor is a program that lets you generate CSS from the preprocessor's own unique syntax.
由上述的說明是一個CSS的預處理器,像是在產生最終的CSS之前,有原始的SCSS檔,然後經CSS預處理器編譯成可以被瀏覽器解析的語法,因此代表要特別去理解經過CSS preprocessor的過程可以帶來什麼方便之處。
目前比較常見的CSS preprocessor是SASS,
官網為 https://sass-lang.com/
在使用SASS之前要先安裝SASS
https://sass-lang.com/install/
下載點為
https://github.com/sass/dart-sass/releases/tag/1.68.0
點選不同系統平台的版本,下載後解壓縮後,將該路徑指定到PATH的變數中,
或是 在node.js的npm模式下
輸入安裝指令
npm install -g sass
在MacOS下可以透過Homebrew安裝
指令為
brew install sass/sass/sass
安裝後可以利用
sass --version
查看版本是來確定是否有安裝成功。
接著以下指令為 將sass的原始檔(input.scss)編譯為css檔(output.css)
sass input.scss output.css
之後若是要在vue的專案檔使用,就可以利用npm來安裝,這樣就跟vue的安裝套件是相同的了
//-------------------------------
接下來是SCSS的語法說明
可以參考SASS官網的介紹
https://sass-lang.com/guide/
基本上 sass/scss 最主要的重點就是可以設定變數,以及一些像是程式般的控制css的屬性
因此,如何增加css設定的彈性以及好維護,就是在使用scss時要一直思考的項目,
而不是為了使用scss而產生更多的工作出來。
先從範例來看範如何使用
編譯前
SCSS
$font-stack: Helvetica, sans-serif;
$primary-color: #333;
body {
font: 100% $font-stack;
color: $primary-color;
}
以及
SASS
$font-stack: Helvetica, sans-serif
$primary-color: #333
body
font: 100% $font-stack
color: $primary-color
以上可以看到有2種SASS格式,最初是使用SASS的格式,就是以縮排的方式來排列SASS的內容,
由於SASS是以Ruby程式語言開發的,而Ruby程式語言的編寫風格就是不使用大括號來界定程式區段的範圍,
而是以縮排的方式界定程式區段的範圍,這種風格也出現在Python程式語言中。
因此SASS就做用了縮排的方式來排列SASS的內容,
不過畢竟是CSS相關,因此另外推出SCSS的格式,也就是使用與CSS相同的以大括號來界定樣式區段的範圍,
這樣在編輯SCSS檔案時,不會差距太大,也算是像是在編寫可程式化的CSS檔的效果
所以SASS或是SCSS指的都是CSS預處理的格式檔案,預處理編譯器則是SASS
然後
編譯後
CSS
body {
font: 100% Helvetica, sans-serif;
color: #333;
}
以下列出一些常見的SCSS的用法
樣式巢狀處理
SCSS
nav {
ul {
margin: 0;
padding: 0;
list-style: none;
}
li {
display: inline-block;
}
a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
}
編譯後
CSS
nav ul {
margin: 0;
padding: 0;
list-style: none;
}
nav li {
display: inline-block;
}
nav a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
可以看出,原本的CSS是不能有巢狀關係的,只能用並列的方式來表示上層與下層的關係
在SCSS中,可以用像是物件屬性的方式,來表示上層與下層的關係
再來是@import的用法,一種可以外部scss檔案匯入的概念,像是全域的樣式匯入
reset.scss
html, body, ul, ol {
margin: 0;
padding: 0;
}
standard.scss
@import "reset";
body {
font-family: Helvetica, sans-serif;
font-size: 18px;
color: red;
}
編譯後
CSS
html, body, ul, ol {
margin: 0;
padding: 0;
}
body {
font-family: Helvetica, sans-serif;
font-size: 18px;
color: red;
}
//-----------------
接著是 @mixin 與 @include 的搭配使用, 比較像是區域的樣式引入
mystyle.scss
@mixin important-text {
color: red;
font-size: 25px;
font-weight: bold;
border: 1px solid blue;
}
.danger {
@include important-text;
background-color: green;
}
編譯後 CSS
mystyle.css
.danger {
color: red;
font-size: 25px;
font-weight: bold;
border: 1px solid blue;
background-color: green;
}
由上可看出 @mixin
像是一個樣式的片段,等著被其他的主要樣式加入或併入
就是 important-text 的樣式片段 加入 @include
到 .danger 樣式中
也可以是有參數帶入的形式
@mixin square($size, $radius: 0) {
width: $size;
height: $size;
@if $radius != 0 {
border-radius: $radius;
}
}
.avatar {
@include square(100px, $radius: 4px);
}
編譯後 CSS
.avatar {
width: 100px;
height: 100px;
border-radius: 4px;
}
//---------------
再來是 @extend
的用法
SCSS
.button-basic {
border: none;
padding: 15px 30px;
text-align: center;
font-size: 16px;
cursor: pointer;
}
.button-report {
@extend .button-basic;
background-color: red;
}
.button-submit {
@extend .button-basic;
background-color: green;
color: white;
}
編譯後 CSS
.button-basic, .button-report, .button-submit {
border: none;
padding: 15px 30px;
text-align: center;
font-size: 16px;
cursor: pointer;
}
.button-report {
background-color: red;
}
.button-submit {
background-color: green;
color: white;
}
這個 @extend
的概念,像是將 .button-basic 引入到 .button-report中
但就編譯後的結果來看,像是將 .button-report 並列到 .button-basic,
有點像是註冊或是掛載到 .button-basic,這樣 .button-basic 的變化就會同步到 .button-report 及 .button-submit中了
//------------------------
接下來,在SCSS中也有支援一些funtion的使用,這個像是原本要使用js控制一些元素的屬性變化,就可以在SCSS檔案中處理了。
分成幾種不同類別的function
有 String,Numeric,List,Map,Selector,Introspection,Color
這些可以看作是原本CSS function 以及 selector function 的擴充
需要使用 @use 來載入function的套件
舉例來說
str-length("Hello world!")
Result: 12
計算字串長度
str-index("Hello world!", "H")
Result: 1
找出字元出現在字串中的位置
要注意的是回傳第一位置的字元的索引index是1 不是0
comparable(15px, 10px)
Result: true --> 同單位,可比較
comparable(35px, 2em)
Result: false --> 不同單位,不可比較
這個是在檢查,這2個數值是否為可比較的數值
random()
Result: 0.45673
取得 0 ~ 1之間的隨機數值
$font-sizes: ("small": 12px, "normal": 18px, "large": 24px)
map-get($font-sizes, "small")
Result: 12px
取得在 $font-sizes中,"small"的數值
這部份的使用地方比較是在樣式屬性的數值設定上需要的一些運算及處理。
這些內建的套件模組有
The sass:math module 數值的操作.
The sass:string module 字串的合併,搜尋,分段
The sass:color module 顏色的操作
The sass:list module 清單的操作,比較像是陣列的操作
The sass:map module 物件(key_value)map 的操作
The sass:selector module 選擇器的操作
The sass:meta module SASS 內部資訊的查詢
以下是一些完整的使用範例
SCSS
$sizes: 40px, 50px, 80px;
@each $size in $sizes {
.icon-#{$size} {
font-size: $size;
height: $size;
width: $size;
}
}
這個使用到@each
,像是loop的概念,可以一次產出不同 $sizes
的icon 樣式
編譯後 CSS
.icon-40px {
font-size: 40px;
height: 40px;
width: 40px;
}
.icon-50px {
font-size: 50px;
height: 50px;
width: 50px;
}
.icon-80px {
font-size: 80px;
height: 80px;
width: 80px;
}
//--------
SASS 有提供 playground 可以測試SCSS 的結果
https://sass-lang.com/playground/
還有完整的文件說明
https://sass-lang.com/documentation/
//---------
另一個範例
SCSS
@use "sass:meta";
@mixin syntax-colors($args...) {
@debug meta.keywords($args);
// (string: #080, comment: #800, variable: #60b)
@each $name, $color in meta.keywords($args) {
pre span.stx-#{$name} {
color: $color;
}
}
}
@include syntax-colors(
$string: #080,
$comment: #800,
$variable: #60b,
)
編譯後 CSS
pre span.stx-string {
color: #080;
}
pre span.stx-comment {
color: #800;
}
pre span.stx-variable {
color: #60b;
}
Console 訊息
@debug:4 (string: #080, comment: #800, variable: #60b)
@debug 相當於 console.log();
$args...
是指 參數列